move semantics 1 תכנות מונחה עצמים ופיתוח משחקים תשע"ו סמנטיקת ההעברה semantics( )Move
move semantics 2 מטרה האצה של התוכניות, שיפור בביצועים על ידי חסכון בבנייה והעתקה של אובייקטים זמניים
move semantics 3 מהם?rvalue, lvalue lvalue משתנה שניתן לגשת אליו בזיכרון )ניתן להפעיל עליו אופרטור &(. rvalue משתנה שאינו.lvalue מתייחס למשתנה זמני, ללא שם, המיועד להערכה זמנית של ביטוי. דוגמאות: int x = 10; // x is an lvalue and 10 is an rvalue int y = 20; // same x = y; // x and y are lvalues (lvalues can be at any side) int* p = &x; // p is an lvalue. Int *q = &10; // error: can t take address of an rvalue x+(y*z); // y*z is an rvalue
move semantics 4 int foo)( { x = foo(); // foo() is an rvalue foo() = 15; // error: can t assign to an rvalue int& goo)( { x = goo(); // fine: assign lvalue into lvalue goo() = 15; // fine: goo() is an lvalue int* p = &goo(); // fine: goo() is an lvalue
move semantics 5 הגדרה מפורשת של משתנה rvalue int& x; // The traditional reference variable (lvalue) int&& x; // C++11 rvalue reference variable
move semantics 6 שכפול לעומת העברה העברת משאבים במקום שכפול של משאבים משפרת את הביצועים. יש מקומות בהם יהיה מיותר לשכפל ודי בהעברת המשאבים. מתאים במיוחד עבור משתנה rvalue שההתייחסות אליהם בלאו הכי זמנית. דוגמא לשכפול: string func() { string s; //do something with s return s; string mystr=func(); // here is a clone of an rvalue
move semantics 7 Copy constructor and assignment class MemoryPage { public: MemoryPage(int sz=512); ~MemoryPage(); //typical C++03 copy ctor and assignment operator (clone resource) private: ; MemoryPage(const MemoryPage&); MemoryPage& operator=(const MemoryPage&); int m_size; char * m_buf;
move semantics 8 Copy constructor and assignment //typical C++03 copy ctor and assignment operator (clone resource) MemoryPage::MemoryPage(const MemoryPage& other) : m_size(other.m_size), m_buf(new char [m_size]) { for (int i=0;i<_size;++i) m_buf[i] = other.m_buf[i]; MemoryPage& MemoryPage::operator=(const MemoryPage& other) { if (this!=&other) { delete[] m_buf; m_size = other.m_size; m_buf = new char[m_size]; for (int i=0;i<m_size;++i) m_buf[i] = other.m_buf[i]; return *this;
move semantics 9 Move constructor and assignment class MemoryPage { public: MemoryPage(int sz=512); ~MemoryPage(); //typical C++03 copy ctor and assignment operator (clone resource) MemoryPage(const MemoryPage&); MemoryPage& operator=(const MemoryPage&); //C++ 11 move constructor and assignment MemoryPage(MemoryPage&&); MemoryPage& operator=(memorypage&&); private: int m_size; char * m_buf; ;
move semantics 10 Move constructor and assignment MemoryPage::MemoryPage(MemoryPage&& other) : m_size(other.m_size), m_buf(other.m_buf) { other.m_size = 0; other.m_buf = nullptr; MemoryPage& MemoryPage::operator=(MemoryPage&& other) { if (this!=&other) { return *this; delete[] m_buf; m_size = other.m_size; m_buf = other.m_buf; other.m_size = 0; other.m_buf = nullptr;
move semantics 11 Test it all // lets add the following functions // member function void MemoryPage::print() { if (m_buf == nullptr) cout << "page is empty" << endl; else cout << "page is not empty" << endl; // non member function MemoryPage read() { cout << "enter page size:" << endl; int size; cin >> size; return MemoryPage(size);
move semantics 12 Test it all int main() { MemoryPage mp1(10); mp1 = read(); mp1 = move(read()); MemoryPage mp2; mp2 = mp1; mp1.print(); mp2 = move(mp1); mp1.print(); // move assignment // explicit move assignment // assignment // mp1 is not empty // explicit move assignment // mp1 is empty
move semantics 13 שילוב עם הספרייה הסטנדרטית הספרייה הסטנדרטית תומכת ברעיונות של סמנטיקת ההעברה פעולות שונות מכילות העמסה )overloading( למשל לפונקציה ארגומנט מסוג ביחס לסמנטיקה זו vector::push_back) ( שתי גרסאות: l-value המתפקד כ-,const T& ארגומנט מסוג המתפקד כ- r-value &&T, )כפי שהכרנו עד כה( )סמנטיקת ההעברה(
move semantics 14 שילוב עם הספרייה הסטנדרטית int main() { vector<memorypage> vm; MemoryPage mp1(1024); //lvalue vm.push_back(mp1); //push_back(const T&) int main() { vector<memorypage> vm; vm.push_back(memorypage(1024)); //push_back(t&&) vm.push_back(memorypage(2048)); //push_back(t&&) MemoryPage mp1(1024); //lvalue vm.push_back(std::move(mp1)); //calls push_back(t&&)
move semantics 15 סיכום כדי לממש סמנטיקת העברה ביחס למחלקה צריך להגדיר: move constructor move assignment operator במקומות בהם ניתן, מתבצעת העברה של אובייקטים במקום העתקה סמנטיקת ההעברה מאפשרת חיסכון ניכר בהעתקות של אובייקטים ולכן מתקבלים ביצועים טובים באופן משמעותי סמנטיקת ההעברה לא מצריכה שינויים בקוד הקיים השקעה קטנה בקידוד המחלקות שמניבה יתרון משמעותי